package com.lenovo.spider.htmlrender

import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.openqa.selenium.By
import org.openqa.selenium.WebDriver
import org.openqa.selenium.phantomjs.PhantomJSDriver
import org.openqa.selenium.remote.DesiredCapabilities
import java.net.URI

/**
 *
 * @author <a href="mailto: 393803588@qq.com">刘涵(Hanl)</a>
 * By 2018/1/17
 */
fun phantomjs(): PhantomJSDriver {
    System.setProperty("phantomjs.binary.path", "/home/hanl/DevTools/phantomjs/bin/phantomjs")
    val desc = DesiredCapabilities.phantomjs()
    desc.setCapability("phantomjs.page.settings.userAgent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11")
    desc.setCapability("phantomjs.page.customHeaders.User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11")
    return PhantomJSDriver(desc)
}


fun renderHtml(url: String?,
               waitTime: Double? = null,
               eventType: String? = null,
               locator: String? = null): String {
    if (url.isNullOrEmpty()) {
        return "Url is empty"
    }
    val driver = phantomjs()
    try {
        driver.get(url)

        // 执行dom事件
        driver.handleEvent(locator, eventType, waitTime)

        val doc = Jsoup.parse(driver.pageSource)

        val base = URI(driver.currentUrl)
        removeElement(doc, "script")

        replaceRelativePath(doc, base, "href")
        replaceRelativePath(doc, base, "src")

        doc.body().appendElement("input")
                .attr("type", "hidden")
                .attr("id", "currentUrl")
                .attr("value", driver.currentUrl)
        doc.body().appendElement("script").attr("src", "http://localhost:8080/static/agent.js")


        return doc.html()
    } catch (e: Exception) {
        return "Render Page Error"
    } finally {
        driver.quit()
    }
}


fun WebDriver.handleEvent(locator: String?, eventType: String?, waitTime: Double?) {
    if (locator == null || eventType == null) return
    //　查找并执行相应时间
    try {
        this.findElement(By.xpath(locator)).run {
            when (eventType) {
                "click" -> {
                    this.click()
                }
                else -> {
                }
            }
        }

        // 执行完，等待一段时间
        waitTime?.run {
            Thread.sleep((waitTime * 1000).toLong())
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}


fun replaceRelativePath(doc: Document, base: URI, attr: String) {
    doc.getElementsByAttribute(attr).forEach {
        val cur = it.attr(attr)
        if (!cur.matches("^(https?|ftp):".toRegex())) {
            val abs = base.resolve(cur).toString()
            it.attr(attr, abs)
        }
    }
}

fun removeElement(doc: Document, tagName: String) {
    doc.getElementsByTag(tagName).remove()
}
